"use strict";
let LessAutoprefix = require('less-plugin-autoprefix');
let fs = require('fs');
let env = require('dotenv');
let uglifyJS = require('uglify-js');
const crypto = require('crypto');

exports.autoprefix = () => {
    return new LessAutoprefix({
        browsers: ['last 5 versions', 'ie >= 10', 'Chrome >= 42', 'ff >= 38', 'Safari >= 7', 'Opera >= 29', 'iOS >= 7.1', 'ie_mob >= 10', 'Android >= 4.4']
    });
};

exports.env = () => {
    if (fs.existsSync('.env'))
        return env.config();
    return { 'ENV': 'development' };
};

/**
 *构建require.js
 * @type {{getDefine: buildConfig.getDefine, transPathToWebPath: buildConfig.transPathToWebPath, toObject: buildConfig.toObject}}
 */
let buildConfig = {
    getDefine: (contents) => {
        let define = '',
            ast = uglifyJS.parse(contents),
            walker = new uglifyJS.TreeWalker((node) => {
                if (node instanceof uglifyJS.AST_String) {
                    let p = walker.parent();
                    if (p.start.value === 'define') {
                        define = node.getValue();
                    }
                }
            });
        ast.walk(walker);
        return define;
    },
    transPathToWebPath: (path) => {
        if (path && path.indexOf('page') > 0) {
            return path.replace(/.*[\w(\\|\/)]+javascripts(\\|\/)page(\\|\/)/g, "/dist/zb/require/").replace(/\\|\\\\/gi, "/");
        }
        return false;
    },
    toObject: (contents, path) => {
        let define = buildConfig.getDefine(contents),
            url = buildConfig.transPathToWebPath(path);
        if (define && url) {
            let version = toSHA1(clearLineBreaks(null, contents.toString('utf8')));
            return `'${define}':{url:'${url}',version:'${version}'},`;
        }
        return '';
    }
};

let actionConfig = {
    prefix: '(function(window){window.actionConfig = {',
    content: '',
    suffix: '};})(window);'
};


exports.transRequire = (contents, mtime, path) => {
    return buildConfig.toObject(contents, mtime, path);
};

exports.buildConfigFile = (content) => {
    actionConfig.content += content;
};
exports.getActionConfig = (content) => {
    let result = actionConfig.prefix + actionConfig.content + actionConfig.suffix;
    return result + content;
};

let clearCSSCharset = (file, contents) => {
    return contents.replace(/^@charset[\s\t]['"]UTF-8['"];/gi, '');
};
let clearCSSCommend = (contents) => {
    return contents.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, '');
};

exports.clearCSSUnuseLine = (file, contents) => {
    return clearCSSCommend(clearCSSCharset(file, contents));
};
let clearLineBreaks = (file, contents) => {
    return contents.replace(/(\r\n|\n|\r)/gm, "");
};
exports.clearLineBreaks = clearLineBreaks;

let toSHA1 = (str) => {
    let hmac = crypto.createHmac('sha1', 'osc');
    hmac.update(str);

    return hmac.digest('hex');
};

exports.toSHA1 = toSHA1;

exports.uglifyOption = {
    // the banner is inserted at the top of the output
    mangle: true,
    preserveComments: false,
    output: {
        indent_start: 0,     // start indentation on every line (only when `beautify`)
        indent_level: 4,     // indentation level (only when `beautify`)
        quote_keys: false, // quote all keys in object literals?
        space_colon: true,  // add a space after colon signs?
        ascii_only: false, // output ASCII-safe? (encodes Unicode characters as ASCII)
        inline_script: false, // escape "</script"?
        width: 80,    // informative maximum line width (for beautified output)
        max_line_len: 32000, // maximum line length (for non-beautified output)
        beautify: false, // beautify output?
        source_map: null,  // output a source map
        bracketize: false, // use brackets every time?
        comments: false, // output comments?
        semicolons: true,  // use semicolons to separate statements? (otherwise, newlines)
    },
    compress: {
        sequences: true,  // join consecutive statemets with the “comma operator” 使用逗号操作符加入连续的简单语句
        properties: true,  // optimize property access: a["foo"] → a.foo 使用点好重写属性访问，例如foo["bar"] → foo.bar
        dead_code: true,  // discard unreachable code 移除不可达的代码
        drop_debugger: true,  // discard “debugger” statements 移除调试器和调试语句
        unsafe: false, // some unsafe optimizations (see below) 应用“不安全”的转换
        conditionals: true,  // optimize if-s and conditional expressions 为if -s 和条件表达式应用优化
        comparisons: true,  // optimize comparisons 针对二进制节点应用某些特定的优化，例如:!(a <= b) → a > b (只在不安全时), 尝试去否认二进制节点，例如.a = !b && !c && !d && !e → a=!(b||c||d||e) 等等.
        evaluate: true,  // evaluate constant expressions 尝试去计算常量表达式
        booleans: true,  // optimize boolean expressions 多种针对布尔上下文的优化，例如 !!a ? b : c → a ? b : c
        loops: true,  // optimize loops 当我们可以静态的判断条件的取值时，针对do,while和for循环的优化
        unused: true,  // drop unused variables/functions 去掉没有被引用过的函数和变量
        hoist_funs: true,  // hoist function declarations 提升函数声明
        hoist_vars: true, // hoist variable declarations (默认值: false) — 提升var声明 (因为一般看起会增加输出的大小，所以它默认是false的)
        if_return: true,  // optimize if-s followed by return/continue 这对 if/return 和 if/continue 的优化
        join_vars: true,  // join var declarations 加入连续的var语句
        cascade: true,  // try to cascade `right` into `left` in sequences 对于 sequences, transform x, x into xandx = something(), x into x = something() 的一些小优化
        side_effects: true,  // drop side-effect-free statements 
        warnings: false,  // warn about potentially dangerous optimizations/code 当去掉不可达代码或者没有被使用的声明等东西时，显示警告.
        drop_console: true, //默认为false.  传入true会丢弃对console.函数的调用.
        global_defs: {
            DEBUG: false // global definitions
        }
    }
};
